#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <poll.h>
#include <string.h>
#include <stdio.h>

#include "World.h"

#define POLLRDHUP 0x2000
#define playerAMNT 4096
#define connectAMNT 64

ssize_t p;
char inbuffer[1024];
char outbuffer[1024];
ssize_t bufferlht = 1024;
struct pollfd newtroll[connectAMNT+ 1];
struct pollfd oldtroll[playerAMNT];
int emptyNBR;
struct playerDATA
{
	int status;
	int sockNUM;
} bronies[playerAMNT], TEMPbronies[connectAMNT];
int ilsock;
struct sockaddr_in listenADDR;
struct sockaddr_in playerADDR[playerAMNT];
struct sockaddr_in TEMPplayerADDR[connectAMNT];
socklen_t playerLHT[playerAMNT];

void playersINIT(void)
// Set initial values and initializes the listening socket
{
	ilsock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
	listenADDR.sin_family = AF_INET;
	listenADDR.sin_addr.s_addr = inet_addr("0.0.0.0");
	listenADDR.sin_port = htons(5234);
	if (bind(ilsock, (struct sockaddr *)&listenADDR, sizeof(listenADDR)) != -1)
	{
		printf("listening socket bound\n");
		if (listen(ilsock, 10) == 0)
		{
			printf("now listening\n");
		}
		else
		{
			printf("I'm not listening\nRestart computer unless you know why\n");
		}
	}
	else
	{
		printf("unbound\nRestart coumpter unless you know what this means\n");
	}
	newtroll[connectAMNT].fd = ilsock;
	newtroll[connectAMNT].events = POLLIN | POLLRDHUP | POLLOUT;
	for (n=0;n<playerAMNT;n++)
	{
		newtroll[n].events = POLLIN | POLLRDHUP | POLLOUT;
	}
}

int checkinput(char *CHECKbuffer, size_t msglen)
//checks if input is of interest to player management
{
	return 42;
}

int playerACTIVE(int q)
// For checking if a player is online
{
	return bronies[q].status;
}

void SENDstuff(int s, char *SENDbuffer, size_t msglen)
//this sends the message in SENDbuffer up to byte msglen to player s
{

}

void newplayer(void)
// Starts login process
{

}

void playerlogin(int t)
// Login process. State machine?
{

}

void goneplayer(int o)
// Closes socket after player hangs up
{
	if(close(bronies[o].sockNUM) == 0)
	{
		printf("Socket shut down\n");
	}
	else
	{
		printf("Socket failed to close\n");
	}
	bronies[o].status = 0;
}

void players(void)
// Main function. Takes data and puts it in inbuffer, sends outbuffer to clients, determine if
// a new client wishes to connect or if an existing client has hung up. Called from main loop.
{
	static int n;
	poll(oldtroll,connectAMNT,0);
	poll(newtroll,playerAMNT,0);
	if ((newtroll[connectAMNT].revents | POLLIN) == 1)
	{
		newplayer();
	}
	for (n = 0;n<connectAMNT;n++)
	{
		if ((newtroll[n].revents | POLLIN) == 1 || (newtroll[n].revents | POLLRDHUP) == 1 || (newtroll[n].revents | POLLOUT) == 1)
		{
			playerlogin(n);
		}
	}
	for (n = 0;n<playerAMNT;n++)
	{
		if ((oldtroll[n].revents | POLLIN) == 1)
		{
			p = recv(bronies(n).sockNUM, inbuffer, bufferlht, 0);
			if (checkinput(inbuffer, p) == 0)
			{
				worldinput(int n, inbuffer);
			}
		}
	}
}
